home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- wind.c
-
- This module handles the commands in the Windows menu. It also contains
- a few general purpose window management functions.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <Icons.h>
- #include <stdio.h>
-
- #include "glob.h"
- #include "full.h"
- #include "menus.h"
- #include "newswatcher.h"
- #include "wind.h"
- #include "dialog.h"
- #include "drawutil.h"
- #include "windutil.h"
- #include "memutil.h"
- #include "strutil.h"
- #include "header.h"
- #include "iconutil.h"
- #include "resutil.h"
- #include "fileutil.h"
- #include "help.h"
-
-
-
- #define kOpenPadlockID 210
- #define kClosedPadlockID 211
-
-
-
- /*----------------------------------------------------------------------------
- DoCycleWindows
-
- Handle the "Cycle Windows" command.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void DoCycleWindows (WindowPtr wind)
- {
- SendBehind(wind, nil);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoZoomWindow
-
- Handle the "Zoom Window" command.
-
- Entry: wind = pointer to window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoZoomWindow (WindowPtr wind)
- {
- WStateData **wState;
- Rect r;
- OSErr err = noErr;
-
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- r = (**wState).stdState;
- if (WindRectEqualRect(wind, &r)) {
- err = DoZoom(wind, inZoomIn);
- } else {
- err = DoZoom(wind, inZoomOut);
- }
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoShowHideFullGroupList
-
- Handle the "Show/Hide Full Group List" command.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoShowHideFullGroupList (void)
- {
- OSErr err = noErr;
-
- if (((WindowPeek)gFullGroupWindow)->visible) {
- HideWindow(gFullGroupWindow);
- SetWindowsMenuShowHideFullGroupList(true);
- } else {
- if (gMustDoZoomOnShowFullGroupList) {
- err = DoZoom(gFullGroupWindow, inZoomOut);
- if (err != noErr) return err;
- }
- gMustDoZoomOnShowFullGroupList = false;
- MyShowWindow(gFullGroupWindow);
- SetWindowsMenuShowHideFullGroupList(false);
- MySelectWindow(gFullGroupWindow);
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- RebuildWindowsMenu
-
- Rebuild the list of open windows in the Windows menu.
- ----------------------------------------------------------------------------*/
-
- void RebuildWindowsMenu (void)
- {
- WindowPtr wind;
- MenuHandle menu;
- Str255 title;
- Str255 menuStr;
- short item, len, numItems, numDel;
- TWindowKind kind;
- TWindow **info;
- Handle fullText;
- CStr255 from;
-
- menu = GetMenuHandle(kWindMenu);
- numItems = CountMItems(menu);
- numDel = numItems - kFirstOpenWindItem + 1;
- while (numDel--) DeleteMenuItem(menu, kFirstOpenWindItem);
- item = kFirstOpenWindItem;
- for (wind = FrontWindow();
- wind != nil;
- wind = (WindowPtr)((WindowPeek)wind)->nextWindow)
- {
- kind = GetMyWindowKind(wind);
- if (kind != kNotOurWind && ((WindowPeek)wind)->visible) {
- GetWTitle(wind, title);
- len = *title;
- if (len > 0 && title[1] == checkMark) {
- len--;
- BlockMoveData(title+2, title+1, len);
- *title = len;
- }
- if (kind == kArticle) {
- info = (TWindow**)GetWRefCon(wind);
- fullText = (**info).fullText;
- if (FindHeaderCString(fullText, "From", from, sizeof(from))) {
- FormatAuthorName(from);
- p2cstr(title);
- sprintf((char*)menuStr, "%.25s, %.200s", from, (char*)title);
- c2pstr((char*)menuStr);
- } else {
- CopyPascalString(menuStr, title);
- }
- } else {
- CopyPascalString(menuStr, title);
- }
- len = *menuStr;
- if (len > 200) {
- len = 200;
- *menuStr = len;
- }
- if (len > 0) {
- if (menuStr[1] == '-') {
- if (len < 255) len++;
- BlockMoveData(menuStr+1, menuStr+2, len-1);
- menuStr[1] = ' ';
- *menuStr = len;
- }
- } else {
- *menuStr = 1;
- menuStr[1] = 'x';
- }
- AppendMenu(menu, "\px");
- SetMenuItemText(menu, item, menuStr);
- if (wind == FrontWindow()) CheckItem(menu, item, true);
- item++;
- }
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- SelectWindMenu
-
- Handle a window selection command in the Windows menu.
-
- Entry: item = item number of menu command.
- ----------------------------------------------------------------------------*/
-
- void SelectWindMenu (short item)
- {
- WindowPtr wind;
-
- item -= kFirstOpenWindItem;
- for (wind = FrontWindow();
- wind != nil;
- wind = (WindowPtr)((WindowPeek)wind)->nextWindow)
- {
- if (GetMyWindowKind(wind) != kNotOurWind && ((WindowPeek)wind)->visible) {
- if (item <= 0) {
- MySelectWindow(wind);
- return;
- } else {
- item--;
- }
- }
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- GetMyWindowKind
-
- Get the window kind.
-
- Entry: wind = pointer to window.
-
- Exit: function result = window kind.
- ----------------------------------------------------------------------------*/
-
- TWindowKind GetMyWindowKind (WindowPtr wind)
- {
- TWindow **info;
- short windowKind;
-
- if (wind == nil) return kNotOurWind;
- windowKind = ((WindowPeek)wind)->windowKind;
- if (windowKind < 0) return kNotOurWind;
- if (windowKind == dialogKind && wind != gMyCurDialog) return kNotOurWind;
- info = (TWindow**)GetWRefCon(wind);
- if (info == nil) return kNotOurWind;
- return (**info).kind;
- }
-
-
-
- /*----------------------------------------------------------------------------
- CreateNewWindow
-
- Create a new window.
-
- Entry: kind = window kind.
- title = window title.
- font = window font.
- size = window font size.
-
- Exit: function result = error code.
- *theWindow = pointer to new window.
- ----------------------------------------------------------------------------*/
-
- OSErr CreateNewWindow (TWindowKind kind, StringPtr title,
- StringPtr font, short size, WindowPtr *theWindow)
- {
- WindowPtr wind = nil, prev, next, behind;
- TWindow **info;
- Rect bounds;
- OSErr err = noErr;
- short fontNum, wDefProcID;
- GrafPtr port;
-
- GetPort(&port);
-
- SetRect(&bounds, 0, 0, 100, 100);
-
- /* Compute the window layer position. If the frontmost window belonging
- to NewsWatcher is the status window, create the new window behind
- the status window. Otherwise, create the new window in front of the
- frontmost window belonging to NewsWatcher. */
-
- prev = nil;
- next = FrontWindow();
- while (next != nil && ((WindowPeek)next)->windowKind < 0) {
- prev = next;
- next = (WindowPtr)((WindowPeek)next)->nextWindow;
- }
- if (GetMyWindowKind(next) == kStatus) {
- behind = next;
- } else if (prev == nil) {
- behind = (WindowPtr)-1;
- } else {
- behind = prev;
- }
-
- wDefProcID = kind == kStatus ? movableDBoxProc : zoomDocProc;
- err = MyNewWindow(&bounds, title, false, wDefProcID, behind, true, 0, &wind);
- if (err != noErr) goto exit;
- SetPort(wind);
-
- GetFontNumber(font, &fontNum);
- TextFont(fontNum);
- TextSize(size);
-
- err = MyNewHandle(sizeof(TWindow), &info);
- if (err != noErr) goto exit;
- (**info).kind = kind;
- SetWRefCon(wind, (long)info);
-
- *theWindow = wind;
- SetPort(port);
- return noErr;
-
- exit:
-
- MyDisposeWindow(wind);
- SetPort(port);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- PositionNewWindow
-
- Position a new window.
-
- Entry: wind = pointer to window.
- width = window width.
- height = window height.
- ----------------------------------------------------------------------------*/
-
- void PositionNewWindow (WindowPtr wind, short width, short height)
- {
- WindowPtr theWind;
- WindowPeek theWindPeek;
- TWindowKind kind;
-
- for (theWind = FrontWindow();
- theWind != nil;
- theWind = (WindowPtr)((WindowPeek)theWind)->nextWindow)
- {
- theWindPeek = (WindowPeek)theWind;
- if (theWindPeek->windowKind < 0) continue;
- if (theWind == wind) continue;
- if (!theWindPeek->visible) continue;
- kind = GetMyWindowKind(theWind);
- if (kind == kStatus || kind == kNotOurWind || kind == kDummy) continue;
- if (gStartingUp && theWind == gFullGroupWindow) continue;
- break;
- }
-
- StaggerWindow(wind, width, height, theWind, gPrefs.dontCoverFinderIcons);
- }
-
-
-
- /*----------------------------------------------------------------------------
- MyShowWindow
-
- Show a window.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void MyShowWindow (WindowPtr wind)
- {
- EventRecord ev;
-
- if (gInBackground) HandleActivate(wind, false);
- ShowWindow(wind);
- while (WaitNextEvent(activMask | osMask, &ev, 0, nil))
- HandleEvent(&ev);
- }
-
-
-
- /*----------------------------------------------------------------------------
- SaveWindPos
-
- Save a window position.
-
- Entry: wind = pointer to window.
-
- Exit: *pos = saved position.
- ----------------------------------------------------------------------------*/
-
- void SaveWindPos (WindowPtr wind, TSavedWindPos *pos)
- {
- TWindow **info;
- GrafPtr port;
- WStateData **wState;
- Rect r, stdState;
-
- info = (TWindow**)GetWRefCon(wind);
- if ((**info).windPosValid) {
- GetPort(&port);
- SetPort(wind);
- pos->valid = true;
- pos->oldFormat = false;
- r = wind->portRect;
- LocalToGlobalRect(&r);
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- stdState = (**wState).stdState;
- pos->zoomed = EqualRect(&stdState, &r);
- if (pos->zoomed) {
- pos->userState = (**wState).userState;
- } else {
- pos->userState = r;
- }
- SetPort(port);
- } else {
- pos->valid = false;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- RestoreWindPos
-
- Restore a window position.
-
- Entry: wind = pointer to window.
- pos = pointer to saved position.
-
- Exit: *needsZooming = true if window should be zoomed.
- ----------------------------------------------------------------------------*/
-
- void RestoreWindPos (WindowPtr wind, TSavedWindPos *pos, Boolean *needsZooming)
- {
- TWindow **info;
- GrafPtr port;
- WStateData **wState;
- Rect r;
- Boolean mainScreen, onOneScreen, useDefaultPos;
- short width, height;
-
- GetPort(&port);
- SetPort(wind);
- info = (TWindow**)GetWRefCon(wind);
-
- useDefaultPos = !pos->valid;
-
- if (!useDefaultPos) {
- MoveWindow(wind, pos->userState.left, pos->userState.top, false);
- if (pos->oldFormat) {
- *needsZooming = true;
- } else {
- width = pos->userState.right - pos->userState.left;
- height = pos->userState.bottom - pos->userState.top;
- SizeWindow(wind, width, height, false);
- *needsZooming = pos->zoomed;
- }
- if (!WindOnScreen(wind)) useDefaultPos = true;
- }
-
- (**info).windPosValid = !useDefaultPos;
-
- if (useDefaultPos) {
- if ((**info).kind == kGroup && (**info).groupKind == kFullGroup) {
- MoveWindow(wind, 10, GetMBarHeight() + 30, false);
- GetDominantScreen(gFullGroupWindow, &r, &mainScreen, &onOneScreen);
- MoveWindow(wind, r.right - wind->portRect.right - 64,
- r.top + GetMBarHeight() + 30, false);
- } else {
- PositionNewWindow(wind, wind->portRect.right, wind->portRect.bottom);
- }
- *needsZooming = true;
- }
-
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- r = wind->portRect;
- LocalToGlobalRect(&r);
- (**wState).userState = r;
-
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- SaveWindPosAsResource
-
- Save a window position as a 'WPOS' id=128 resource on the current
- resource file.
-
- Entry: wind = pointer to window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr SaveWindPosAsResource (WindowPtr wind)
- {
- TSavedWindPos pos;
- Handle h = nil;
- OSErr err = noErr;
- TWindow **info;
-
- SaveWindPos(wind, &pos);
- err = MyPtrToHand(&pos, &h, sizeof(pos));
- if (err != noErr) goto exit;
- err = MyReplaceResource(h, 'WPOS', 128, "\p");
- if (err != noErr) goto exit;
- info = (TWindow**)GetWRefCon(wind);
- (**info).movedSinceLastSave = false;
- return noErr;
-
- exit:
-
- MyDisposeHandle(h);
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- SaveWindPosToFile
-
- If necessary, save just a changed window position to a document file,
- without changing the window's last mod date.
-
- Entry: wind = pointer to window.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr SaveWindPosToFile (WindowPtr wind)
- {
- TWindow **info;
- AliasHandle alias;
- FSSpec fSpec;
- OSErr err = noErr;
- Boolean wasChanged;
- short refNum = 0;
- unsigned long lastModDateTime;
- FInfo fInfo;
-
- /* Note that errors are ignored. This is not a critical operation,
- and we don't want to interfere with closing a window just because
- something fails here. */
-
- info = (TWindow**)GetWRefCon(wind);
- alias = (**info).alias;
- if (alias == nil || !(**info).movedSinceLastSave) return noErr;
- err = ResolveAlias(nil, alias, &fSpec, &wasChanged);
- if (err != noErr) return noErr;
- err = FSpGetFInfo(&fSpec, &fInfo);
- if (err != noErr) return noErr;
- if (fInfo.fdCreator != kNewsWatcherSignature) return noErr;
- err = GetLastModDateTime(&fSpec, &lastModDateTime);
- if (err != noErr) return noErr;
- err = MyFSpOpenResFile(&fSpec, fsRdWrPerm, &refNum);
- if (err != noErr) return noErr;
- err = SaveWindPosAsResource(wind);
- if (err != noErr) goto exit;
- MyCloseResFile(refNum);
- err = SetLastModDateTime(&fSpec, lastModDateTime);
- return noErr;
-
- exit:
-
- if (refNum != 0) MyCloseResFile(refNum);
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- RestoreLockedWindowPosition
-
- Restore a locked window position.
-
- Entry: wind = pointer to subject, article, or message window.
- width = unlocked width of window.
- height = unlocked height of window.
- windPosLocked = true if this kind of window has a saved
- locked position.
- *windLocn = saved locked window position.
-
- If this kind of window has a saved locked window position, and if
- no other window of this kind is already open, the saved locked window
- position is restored. Otherwise, the default window postion is set.
- ----------------------------------------------------------------------------*/
-
- void RestoreLockedWindowPosition (WindowPtr wind, short width, short height,
- Boolean windPosLocked, Rect *windLocn)
- {
- TWindow **info;
- TWindowKind kind;
- WindowPtr w;
- GrafPtr port;
- WStateData **wState;
- Rect r;
-
- GetPort(&port);
- SetPort(wind);
-
- info = (TWindow**)GetWRefCon(wind);
- kind = (**info).kind;
-
- if (windPosLocked) {
- for (w = FrontWindow(); w != nil; w = (WindowPtr)((WindowPeek)w)->nextWindow) {
- if (kind == GetMyWindowKind(w) && w != wind) {
- windPosLocked = false;
- break;
- }
- }
- }
-
- if (windPosLocked) {
- MoveWindow(wind, windLocn->left, windLocn->top, false);
- SizeWindow(wind, windLocn->right - windLocn->left,
- windLocn->bottom - windLocn->top, false);
- if (WindOnScreen(wind)) {
- wState = (WStateData**)((WindowPeek)wind)->dataHandle;
- r = wind->portRect;
- LocalToGlobalRect(&r);
- (**wState).userState = r;
- } else {
- windPosLocked = false;
- }
- }
-
- if (!windPosLocked) {
- PositionNewWindow(wind, width, height);
- }
-
- (**info).windPosLocked = windPosLocked;
-
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- DrawPadlockIcon
-
- Draw the padlock icon in a window.
-
- Entry: wind = pointer to subject, article, or message window.
- ----------------------------------------------------------------------------*/
-
- void DrawPadlockIcon (WindowPtr wind)
- {
- TWindow **info;
- short windHeight;
- Rect padlockRect;
-
- info = (TWindow**)GetWRefCon(wind);
- windHeight = wind->portRect.bottom;
- SetRect(&padlockRect, 1, windHeight-17, 17, windHeight-1);
- PlotIconID(&padlockRect, 0, ttNone,
- (**info).windPosLocked ? kClosedPadlockID : kOpenPadlockID);
- }
-
-
-
- /*----------------------------------------------------------------------------
- HandlePadlockClick
-
- Check for and handle a click on a padlock icon.
-
- Entry: wind = pointer to subject, article, or message window.
- where = location of mouse down event, in local coords.
- windPosLocked = pointer to windPosLocked preference for
- this kind of window.
- windLocn = pointer to saved locked window position for
- this kind of window.
-
- Exit: function result = true if padlock clicked.
- ----------------------------------------------------------------------------*/
-
- Boolean HandlePadlockClick (WindowPtr wind, Point where,
- Boolean *windPosLocked, Rect *windLocn)
- {
- TWindow **info;
- short windHeight, iconID;
- Rect padlockRect, hotRect;
- GrafPtr port;
- WindowPtr w;
- TWindowKind kind;
-
- GetPort(&port);
- SetPort(wind);
-
- info = (TWindow**)GetWRefCon(wind);
- windHeight = wind->portRect.bottom;
- SetRect(&padlockRect, 0, windHeight-16, 16, windHeight);
- hotRect = padlockRect;
- hotRect.top += 2;
- hotRect.right -= 1;
- iconID = (**info).windPosLocked ? kClosedPadlockID : kOpenPadlockID;
-
- if (!TrackIconClick(where, &padlockRect, &hotRect, iconID)) {
- SetPort(port);
- return false;
- }
-
- SetRect(&padlockRect, 0, windHeight - 13, 13, windHeight);
-
- (**info).windPosLocked = *windPosLocked = !(**info).windPosLocked;
- InvalRect(&padlockRect);
- if (*windPosLocked) {
- *windLocn = wind->portRect;
- LocalToGlobalRect(windLocn);
- SetPort(port);
- kind = (**info).kind;
- for (w = FrontWindow(); w != nil; w = (WindowPtr)((WindowPeek)w)->nextWindow) {
- if (kind == GetMyWindowKind(w) && w != wind) {
- info = (TWindow**)GetWRefCon(w);
- if ((**info).windPosLocked) {
- (**info).windPosLocked = false;
- SetPort(w);
- windHeight = w->portRect.bottom;
- SetRect(&padlockRect, 0, windHeight - 13, 13, windHeight);
- InvalRect(&padlockRect);
- }
- }
- }
- }
- KillBalloon();
- SetPort(port);
- return true;
- }
-
-
-
- /*----------------------------------------------------------------------------
- RecordNewLockedWindowPosition
-
- Record the new locked window position after a locked window is resized.
-
- Entry: wind = pointer to subject, article, or message window.
- windLocn = pointer to saved locked window position for
- this kind of window.
-
- Exit: *windLocn = new locked window position.
- ----------------------------------------------------------------------------*/
-
- void RecordNewLockedWindowPosition (WindowPtr wind, Rect *windLocn)
- {
- TWindow **info;
- GrafPtr port;
-
- info = (TWindow**)GetWRefCon(wind);
- if (!(**info).windPosLocked) return;
- *windLocn = wind->portRect;
- GetPort(&port);
- SetPort(wind);
- LocalToGlobalRect(windLocn);
- SetPort(port);
- }
-
-
-
- /*----------------------------------------------------------------------------
- MySelectWindow
-
- Move a window to the front, or just behind the Status window if the
- Status window is open.
-
- Entry: wind = pointer to window.
- ----------------------------------------------------------------------------*/
-
- void MySelectWindow (WindowPtr wind)
- {
- WindowPtr front;
- WindowRef wRef;
-
- front = MyFrontWindow();
- if (GetMyWindowKind(front) == kStatus) {
- wRef = (WindowRef)wind;
- PaintOne(wRef, ((WindowPeek)wRef)->strucRgn);
- CalcVis(wRef);
- SendBehind(wind, front);
- } else {
- SelectWindow(wind);
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- AdjustWindowTitlesOnResume
-
- Adjust the titles of all open windows which correspond to saved files
- on a resume event, in case the user changed the file names.
- ----------------------------------------------------------------------------*/
-
- void AdjustWindowTitlesOnResume (void)
- {
- WindowPtr wind;
- TWindowKind kind;
- TWindow **info;
- FSSpec fSpec;
- Boolean wasChanged;
- OSErr err = noErr;
- Str255 title;
-
- for (wind = FrontWindow();
- wind != nil;
- wind = (WindowPtr)((WindowPeek)wind)->nextWindow)
- {
- kind = GetMyWindowKind(wind);
- if (kind != kGroup && kind != kMessage) continue;
- info = (TWindow**)GetWRefCon(wind);
- if ((**info).alias == nil) continue;
- err = ResolveAlias(nil, (**info).alias, &fSpec, &wasChanged);
- if (err == noErr) {
- GetWTitle(wind, title);
- if (EqualString(title, fSpec.name, false, true)) continue;
- SetWTitle(wind, fSpec.name);
- } else {
- MyDisposeHandle((**info).alias);
- (**info).alias = nil;
- (**info).changed = true;
- }
- }
- }